﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using MultiFileUploader.ServiceReference;

namespace MultiFileUploader
{
    [ScriptableType]
    public partial class MainPage : UserControl
    {
        private FileServiceClient _fileServiceClient;
        private int _numOfFilesUploaded;
        private int _numOfFilesToUpload;
        private bool _aspNetPageInformed;
        private IList<string> _uploadedFileNameList;
        private static readonly int _maxPhotoSize = 2048;
        private static readonly int _maxNumOfUploadPhotos = 12;
        private static readonly string _notifyUploadCompleteScriptName = "NotifyUploadComplete";
        private static readonly string _setProgressGifVisibilityScriptName = "SetUploadingGifVisibility";

        public MainPage()
        {
            InitializeComponent();
            HtmlPage.RegisterScriptableObject("MainPage", this);

            _fileServiceClient = new FileServiceClient();
            _uploadedFileNameList = new List<string>();
            _numOfFilesUploaded = 0;
   
            _fileServiceClient.UploadFileCompleted += UploadFile_Completed;
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            // Make sure the dyanmic URL is set (for testing).
            EndpointAddress address = new EndpointAddress( "http://localhost:" + HtmlPage.Document.DocumentUri.Port + "/FileService.svc" );
            _fileServiceClient.Endpoint.Address = address;
        }

        // user click on the button on the UI to select file(s) to upload 
        private void SelectFileClick(object sender, RoutedEventArgs e)
        {
            if (_uploadedFileNameList.Count >= _maxNumOfUploadPhotos)
            {
                return;
            }
            
            OpenFileDialog openDialog = new OpenFileDialog();

            openDialog.Multiselect = true;
            openDialog.Filter = "Image Files (.jpg,.gif,.png)|*.jpg;*.gif;*.png";

            if (openDialog.ShowDialog() == true)
            {
                // user clicked on ok and start uploading selected files
                if (openDialog.File != null)
                {
                    UploadAllFiles(openDialog.Files);
                }
            }
        }

        private void UploadAllFiles(IEnumerable<FileInfo> fileInfoList)
        {
            int totalNumOfPhotosIfUploaded = fileInfoList.Count() + _uploadedFileNameList.Count;
            
            // set the max number of photos to upload
            if (totalNumOfPhotosIfUploaded > _maxNumOfUploadPhotos)
            {
                fileInfoList = fileInfoList.Take(_maxNumOfUploadPhotos - _uploadedFileNameList.Count);
            }

            _numOfFilesToUpload = fileInfoList.Count();
            
            // reset all the variables so we can add more photos
            _numOfFilesUploaded = 0;
            _aspNetPageInformed = false;

            HtmlPage.Window.Invoke(_setProgressGifVisibilityScriptName, true);
            
            foreach (FileInfo fileInfo in fileInfoList)
            {
                if (IsOkToUploadFile(fileInfo))
                {
                    UploadFileToServer(fileInfo);
                }
            } 
        }
        
        // max file size is 2MB
        private bool IsOkToUploadFile(FileInfo fileInfo)
        {
            try
            {
                return GetFileSizeInKB(fileInfo.Length) <= _maxPhotoSize;
            }
            catch (Exception)
            {
                // when any exception occurs (the file is deleted somehow), just return false and this file will not be uploaded
                return false;
            }
        }

        private long GetFileSizeInKB(long fileSizeInByte)
        {
            if (fileSizeInByte < 1024)
            {
                return 1;
            }

            return fileSizeInByte / 1024;
        }

        private void UploadFileToServer(FileInfo fileInfo)
        {
            try
            {
                using (Stream stream = fileInfo.OpenRead())
                {
                    byte[] data = new byte[stream.Length];
                    stream.Read(data, 0, (int)stream.Length);

                    _fileServiceClient.UploadFileAsync(fileInfo.Name, data);
                }
            }
            catch (Exception)
            {
                // when any exception occurs, just return false and this file will be skipped
                return;
            }
        }

        private void UploadFile_Completed(object sender, UploadFileCompletedEventArgs e)
        {
            string fileNameOnServer = string.Empty;

            try
            {
                fileNameOnServer = e.Result;
            }
            catch (Exception)
            {
                _numOfFilesUploaded++;
                return;
            }

            _numOfFilesUploaded++;

            if (!string.IsNullOrEmpty(fileNameOnServer))
            {
                _uploadedFileNameList.Add(fileNameOnServer);
            }

            NotifyAspnetPageIfNeccessary();
        }

        private void NotifyAspnetPageIfNeccessary()
        {
            if (_numOfFilesUploaded == _numOfFilesToUpload)
            {
                lock (this)
                {
                    if (_aspNetPageInformed)
                    {
                        return;
                    }

                    _aspNetPageInformed = true;

                    string filenames = string.Join(",", _uploadedFileNameList.ToArray());
                    HtmlPage.Window.Invoke(_setProgressGifVisibilityScriptName, false);

                    // call a javascript function in aspx to display all thumbnails
                    HtmlPage.Window.Invoke(_notifyUploadCompleteScriptName, filenames);
                }
            }
        }

        [ScriptableMember]
        public void DeleteUploadedPhoto(string photoName)
        {
            try
            {
                _uploadedFileNameList.Remove(photoName);
            }
            catch (Exception)
            {
            }
        }
    }
}
